<script setup lang="ts">
import { computed, ref } from "vue";
import CallHistory from "@/components/CallHistory/index.vue";
import { getClassList } from "@/api/classes";
import { getStudentListApi } from "@/api/student";
import { addHistoryApi } from "@/api/call-history";
import { ElMessage } from "element-plus";

const curClass = ref();
const classList = ref([]);
const studentList = ref([]);
const curStudent = ref({ text: "准备开始" });
const stuTotal = computed(() => {
  return studentList.value.length;
});

const getClassesList = async function () {
  const result = await getClassList();
  const list = result.data ?? [];
  classList.value = list;
  curClass.value = list[0];
  await getStudentList();
};

const getStudentList = async function () {
  if (!curClass.value) return;
  const param = {
    class_id: curClass.value.class_id
  };
  const { data } = await getStudentListApi(param);
  const list = data.list ?? [];
  studentList.value = list;
};

getClassesList();

// 点名
const speed = 60;
const originDownCount = 3;
const downCount = ref(originDownCount);
const downLoading = ref(false);
const isResult = ref(false);
let callTimer;
let downTimer;
const stopCall = function () {
  clearInterval(downTimer);
  clearInterval(callTimer);
  downLoading.value = false;
  downCount.value = originDownCount;
  isResult.value = true;
};
const handleCall = function () {
  if (!stuTotal.value) return;

  if (downLoading.value) {
    return stopCall();
  }

  downLoading.value = true;
  isResult.value = false;
  downTimer = setInterval(() => {
    downCount.value--;
    if (!downCount.value) {
      stopCall();
    }
  }, 1000);
  callTimer = setInterval(() => {
    const target = getSecureRandomStudent(studentList.value);
    curStudent.value = { ...target, text: target.stu_name };
  }, speed);
};

const getSecureRandomStudent = function (stuList) {
  if (stuList.length === 0) return null;

  const randomArray = new Uint32Array(1);
  window.crypto.getRandomValues(randomArray);

  const index = randomArray[0] % stuList.length;
  return stuList[index];
};

const addHistory = function (status) {
  const params = {
    stu_id: curStudent.value.stu_id,
    stu_name: curStudent.value.stu_name,
    class_name: curClass.value.class_name,
    is_absent: status
  };
  isResult.value = false;
  addHistoryApi(params).then(res => {
    const msg = `已记录“${params.stu_name}”${status ? "缺勤" : "已到"}`;
    ElMessage.success(msg);
    curTimestamp.value = String(Date.now());
  });
};

const curTimestamp = ref("");
</script>

<template>
  <div class="page-container">
    <div :class="['board', { result: isResult }]">
      <div class="stu-name">{{ curStudent.text }}</div>
      <div v-if="curClass" class="class-name">
        {{ curClass.class_name }}
      </div>
      <div v-if="isResult" class="absent-btn">
        <ElButton type="danger" @click="addHistory(1)">缺勤</ElButton>
      </div>
      <div v-if="isResult" class="attend-btn">
        <ElButton type="success" @click="addHistory(0)">已到</ElButton>
      </div>
    </div>
    <div class="operation-box">
      <div
        :class="['call-btn', { danger: downLoading, disabled: !stuTotal }]"
        @click="handleCall"
      >
        <span>{{ downLoading ? "停止点名" : "开始点名" }}</span>
        <span v-show="downLoading">（{{ downCount }}秒后自动停）</span>
      </div>
    </div>
    <div class="student-container">
      <div class="container-header">
        <span class="title">学生名单</span>
      </div>
      <div>
        <ElSelect
          v-model="curClass"
          class="class-select"
          value-key="class_id"
          placeholder="请选择班级"
          @change="getStudentList"
        >
          <ElOption
            v-for="item in classList"
            :key="item.class_id"
            :label="item.class_name"
            :value="item"
          />
        </ElSelect>
        <span class="stu-count">当前班级学生数 {{ stuTotal }}</span>
      </div>

      <div class="student-list">
        <ElTag
          v-for="item in studentList"
          :key="item.stu_id"
          :disable-transitions="true"
          class="stu-tag"
          type="primary"
          effect="dark"
          round
        >
          {{ item.stu_name }}
        </ElTag>
      </div>
    </div>
    <div class="history-container">
      <div class="container-header">
        <span class="title">点名历史</span>
      </div>

      <CallHistory :timestamp="curTimestamp" />
    </div>
  </div>
</template>

<style scoped lang="scss">
.page-container {
  .board {
    height: 50vh;
    border-radius: 4px;
    background: #ecf5ff;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    position: relative;

    .stu-name {
      font-size: 40px;
      line-height: 1.5;
      text-align: center;
      color: #409eff;
    }

    .class-name {
      color: #666;
      margin-top: 20px;
      visibility: hidden;
    }

    .absent-btn {
      position: absolute;
      left: 10px;
      bottom: 10px;
    }

    .attend-btn {
      position: absolute;
      right: 10px;
      bottom: 10px;
    }
  }

  .board.result {
    background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%);

    .stu-name {
      color: #2e7d32;
      animation: rubberBand 1s;
    }

    .class-name {
      visibility: visible;
    }
  }

  .operation-box {
    text-align: center;
    padding: 20px 0;

    .call-btn {
      border-radius: 4px;
      color: #fff;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      user-select: none;
      height: 60px;
      width: 100%;
      background: #409eff;

      &.danger {
        background: #f56c6c;
      }

      &.disabled {
        opacity: 0.6;
        cursor: no-drop;
      }
    }
  }

  .student-container {
    .class-select {
      width: 200px;
    }

    .stu-count {
      margin-left: 10px;
      font-size: 12px;
    }

    .student-list {
      padding: 20px 10px 10px;
      display: flex;
      flex-wrap: wrap;
      gap: 10px;
    }
  }

  .container-header {
    margin: 40px 0 10px;

    .title {
      font-size: 18px;
      font-weight: 700;
      color: #333;
    }
  }
}

@keyframes rubberBand {
  0% {
    transform: scaleX(1);
  }

  30% {
    transform: scale3d(1.25, 0.75, 1);
  }

  40% {
    transform: scale3d(0.75, 1.25, 1);
  }

  50% {
    transform: scale3d(1.15, 0.85, 1);
  }

  65% {
    transform: scale3d(0.95, 1.05, 1);
  }

  75% {
    transform: scale3d(1.05, 0.95, 1);
  }

  to {
    transform: scaleX(1);
  }
}
</style>
